package com.zifeng.rocketmq;

import com.alibaba.fastjson.JSON;
import com.zifeng.common.R;
import com.zifeng.feign.OrderFeignClient;
import com.zifeng.pojo.Order;
import com.zifeng.pojo.ShipDto;
import com.zifeng.service.impl.ShipServiceImpl;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.annotation.RocketMQTransactionListener;
import org.apache.rocketmq.spring.core.RocketMQLocalTransactionListener;
import org.apache.rocketmq.spring.core.RocketMQLocalTransactionState;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;

import static com.zifeng.exception.ErrorCodeAndMsg.ORDER_FEIGN_SELECT_BY_ID_FAIL_CODE;

// 生产者事务监听器类
@Slf4j
@RocketMQTransactionListener
public class TransactionListener implements RocketMQLocalTransactionListener {

    @Autowired
    private ShipServiceImpl shipService;

    @Resource
    private OrderFeignClient orderFeignClient;

    // 监听订单消息
    @Override
    public RocketMQLocalTransactionState executeLocalTransaction(Message message, Object arg) {
        try {
            Order order = JSON.parseObject(message.getPayload().toString(), Order.class);
            if(arg instanceof ShipDto shipDto) {
                shipService.doMysqlLocalTransaction(order, shipDto);
                return RocketMQLocalTransactionState.COMMIT; // 提交事务
            }else {
                log.error("事务消息参数错误，arg不是ShipDto类型, arg: {}", arg);
                return RocketMQLocalTransactionState.ROLLBACK; // 回滚事务
            }
        }catch (Exception e) {
            log.error("执行本地事务失败，异常信息: {}", e.getMessage(), e);
            // 发生异常，回滚事务
            return RocketMQLocalTransactionState.ROLLBACK;
        }
    }

    @Override
    public RocketMQLocalTransactionState checkLocalTransaction(Message message) {
        // 因为这里远程创建订单处于分布式事务中，所以只要确定订单执行成功，就可以确定整个分布式事务执行成功
        Order order = JSON.parseObject(message.getPayload().toString(), Order.class);
        R r = orderFeignClient.getOrder(order.getId());
        if(r.get("code").equals(ORDER_FEIGN_SELECT_BY_ID_FAIL_CODE)) {
            log.error("分布式事务执行失败，订单ID：{}", order.getId());
            return RocketMQLocalTransactionState.ROLLBACK; // 回滚事务
        }
        return RocketMQLocalTransactionState.COMMIT;
    }
}
